<template>
  <el-dialog top="7vh" title="流程图绘制及节点信息设置" class="bpmn" :visible.sync="isVisiable" width="90vw" :close-on-click-modal="false" @close="cacel()">
    <div class="containers" ref="content">
      <div class="canvas" ref="canvas"></div>
      <div id="js-properties-panel" class="panel"></div>
    </div>
    <div class="szbnt">
      <!-- <el-button style="float:right;margin-left: 10px;" type="success" @click="cacel">关闭</el-button> -->
      <el-button style="float:right;margin-left: 10px;" type="success" @click="save">保存流程</el-button>
      <el-button style="float:right" type="primary" @click="szjd" v-show="selectType=='JD'&&undodata.length==1">节点配置</el-button>
      <el-button style="float:right" type="primary" @click="szfz" v-show="selectType=='FZ'&&undodata.length==1">分支配置</el-button>
      <el-button style="float:right" type="warning" @click="undo" icon="el-icon-d-arrow-left" v-show="undodata.length>1" circle>{{undodata.length-1}}</el-button>
    </div>
    <task ref="task"></task>
    <gateway ref="gateway"></gateway>
  </el-dialog>
</template>

<script>
import {getObj, putObj} from '@/api/workflow/wfflowconfig'
import { Message } from "element-ui";
import BpmnModeler from "bpmn-js/lib/Modeler";
import Modeling from "bpmn-js/lib/features/modeling/Modeling";
import propertiesPanelModule from "bpmn-js-properties-panel";
import propertiesProviderModule from "bpmn-js-properties-panel/lib/provider/camunda";
import camundaModdleDescriptor from "camunda-bpmn-moddle/resources/camunda";
import task from "./task";
import gateway from "./gateway";

export default {
  components: {
    task,
    gateway
  },
  data() {
    return {
      isVisiable: false,
      mainInfo: {},
      bpmnModeler: null,
      container: null,
      canvas: null,
      selectType: null,
      selectId: null,
      selectData: null,
      undodata: [],
      eventCinding: false
    };
  },
  created: function () { },
  mounted() { },
  methods: {
    init(id) {
      this.mainInfo = {};
      this.selectType = null;
      this.selectId = null;
      this.selectData = null;
      getObj(id)
        .then(res => {
          if (res.data.code == "0") {
            this.mainInfo = res.data.data;
            var xml = this.mainInfo.flowInfoBase;
            if (xml == null || xml == "") {
              xml = '<?xml version="1.0" encoding="UTF-8"?>';
              xml +=
                '<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" id="sample-diagram" targetNamespace="http://bpmn.io/schema/bpmn" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd">';
              xml += '  <bpmn2:process id="Process_Main">';
              xml += "  </bpmn2:process>";
              xml += '  <bpmndi:BPMNDiagram id="BPMNDiagram_Main">';
              xml +=
                '    <bpmndi:BPMNPlane id="BPMNPlane_Main" bpmnElement="Collaboration_Main">';
              xml += "    </bpmndi:BPMNPlane>";
              xml += "  </bpmndi:BPMNDiagram>";
              xml += "</bpmn2:definitions>";
            }
            this.isVisiable = true;
            this.$nextTick(() => {
              this.$nextTick(() => {
                this.createNewDiagram(xml);
              });
            });
          } else {
            this.$message({
              type: "error",
              message: res.msg
            });
          }
        })
        .catch(() => {
          this.$message({
            type: "info",
            message: "操作错误"
          });
        });
    },
    createNewDiagram(xml) {
      // 获取到属性ref为“content”的dom节点
      this.container = this.$refs.content;
      // 获取到属性ref为“canvas”的dom节点
      const canvas = this.$refs.canvas;

      // 建模，官方文档这里讲的很详细
      if (this.bpmnModeler == null) {
        this.bpmnModeler = new BpmnModeler({
          container: canvas //,
          // 添加控制板
          // propertiesPanel: {
          //     //parent: '#js-properties-panel'
          //     parent: null
          // },
          // additionalModules: [
          //     // 左边工具栏以及节点
          //     propertiesProviderModule,
          //     // 右边的工具栏
          //     propertiesPanelModule
          // ],
          // moddleExtensions: {
          //     camunda: camundaModdleDescriptor
          // }
        });
      }
      // this.container.removeClass('with-diagram');
      $(".bpmn-icon-space-tool").remove();
      $(".bpmn-icon-connection-multi").remove();
      $(".bjs-powered-by").remove();
      $(".bpmn-icon-intermediate-event-none").remove();
      $(".bpmn-icon-subprocess-expanded").remove();
      $(".bpmn-icon-data-store").remove();
      $(".bpmn-icon-end-event-none").remove();
      $(".bpmn-icon-data-object").remove();
      $(".bpmn-icon-gateway-none").remove();
      //$(".bpmn-icon-task").remove();
      var that = this;
      // 将字符串转换成图显示出来
      ////console.log(xml)
      this.bpmnModeler.importXML(xml, function (err) {
        if (err) {
          console.error(err);
        } else {
          that.success();
          // 让图能自适应屏幕
          var canvas = that.bpmnModeler.get("canvas");
          canvas.zoom("fit-viewport");
        }
      });
    },
    success() {
      const bpmnjs = this.bpmnModeler;
      const eventBus = bpmnjs.get("eventBus");
      const elementFactory = bpmnjs.get("elementFactory");
      const modeling = new Modeling(eventBus, elementFactory);
      this.undodata = [];
      var that = this;
      that.bpmnModeler.saveXML({ format: true }, function (err, xml) {
        that.undodata.push(xml);
      });
      if (!this.eventCinding) {
        this.addBpmnListener(this, modeling);
        bpmnjs.on("commandStack.changed", function (e) {
          that.bpmnModeler.saveXML({ format: true }, function (err, xml) {
            that.undodata.push(xml);
          });
        });
        this.eventCinding = true;
      }
    },
    addBpmnListener(_self, modeling) {
      const bpmnjs = this.bpmnModeler;
      const eventBus = bpmnjs.get("eventBus");
      const events = ["element.click", "element.dblclick"];
      var that = this;
      events.forEach(function (event) {
        eventBus.on(event, function (e) {
          that.selectType = "";
          that.selectId = "";
          if (e.element.type == "bpmn:Process" || e.element.type == "bpmn:Lane")
            return;
          // if(['bpmn:Task','bpmn:UserTask','bpmn:ManualTask','bpmn:BusinessRuleTask'].indexOf(e.element.type)!=-1)
          if (
            [
              "bpmn:Task",
              "bpmn:UserTask",
              "bpmn:ManualTask",
              "bpmn:BusinessRuleTask",
              "bpmn:EndEvent"
            ].indexOf(e.element.type) != -1
          ) {
            that.selectType = "JD";
            that.selectId = e.element.id;
            that.selectData = e.element;
          }
          //if(["bpmn:ExclusiveGateway","bpmn:ParallelGateway","bpmn:ComplexGateway"].indexOf(e.element.type)!=-1){
          if (
            ["bpmn:ExclusiveGateway", "bpmn:ParallelGateway"].indexOf(
              e.element.type
            ) != -1
          ) {
            that.selectType = "FZ";
            that.selectId = e.element.id;
            that.selectData = e.element;
          }
        });
      });
    },
    //获取所有节点分支信息
    getFlowConfigLine(xml) {
      var flowConfigLine = {};
      var xotree = new XML.ObjTree();
      var dumper = new JKL.Dumper();
      var tree = xotree.parseXML(xml);
      var json_obj = JSON.parse(dumper.dump(tree));
      if (json_obj["bpmn2:definitions"]["bpmn2:process"] != undefined) {
        var processs = [];
        flowConfigLine["StartEvent"] = [];
        flowConfigLine["StartTask"] = [];
        flowConfigLine["Task"] = [];
        flowConfigLine["Flow"] = [];
        flowConfigLine["Gateway"] = [];
        flowConfigLine["EndEvent"] = [];
        if (
          json_obj["bpmn2:definitions"]["bpmn2:process"].__proto__.constructor
            .name == "Object"
        ) {
          processs.push(json_obj["bpmn2:definitions"]["bpmn2:process"]);
        } else {
          processs = json_obj["bpmn2:definitions"]["bpmn2:process"];
        }
        for (var x = 0; x < processs.length; x++) {
          var process = processs[x];
          var startEventLine = [];

          if (process["bpmn2:startEvent"] != undefined) {
            var startEvents = [];
            if (
              process["bpmn2:startEvent"].__proto__.constructor.name == "Object"
            ) {
              startEvents.push(process["bpmn2:startEvent"]);
            } else {
              startEvents = process["bpmn2:startEvent"];
            }
            for (var j = 0; j < startEvents.length; j++) {
              var startEvent = startEvents[j];
              flowConfigLine["StartEvent"].push(startEvent["-id"]);
              startEventLine.push(startEvent["bpmn2:outgoing"]);
              flowConfigLine[startEvent["-id"]] = {
                id: startEvent["-id"],
                type: "startEvent",
                outgoing: startEvent["bpmn2:outgoing"]
              };
            }
          }

          var tasks = [];
          if (process["bpmn2:task"] != undefined) {
            tasks.push("bpmn2:task");
          }
          if (process["bpmn2:userTask"] != undefined) {
            tasks.push("bpmn2:userTask");
          }
          if (process["bpmn2:manualTask"] != undefined) {
            tasks.push("bpmn2:manualTask");
          }
          if (process["bpmn2:businessRuleTask"] != undefined) {
            tasks.push("bpmn2:businessRuleTask");
          }
          for (var i = 0; i < tasks.length; i++) {
            var type = [];
            if (process[tasks[i]].__proto__.constructor.name == "Object") {
              type.push(process[tasks[i]]);
            } else {
              type = process[tasks[i]];
            }
            for (var j = 0; j < type.length; j++) {
              var task = type[j];
              flowConfigLine[task["-id"]] = {
                id: task["-id"],
                name: task["-name"],
                type: "Task",
                types: tasks[i].replace("bpmn2:", "")
              };
              flowConfigLine["Task"].push(task["-id"]);
              if (task["bpmn2:incoming"] != undefined) {
                flowConfigLine[task["-id"]]["incoming"] =
                  typeof task["bpmn2:incoming"] == "string"
                    ? [task["bpmn2:incoming"]]
                    : task["bpmn2:incoming"];
                if (typeof task["bpmn2:incoming"] == "string") {
                  if (startEventLine.indexOf(task["bpmn2:incoming"]) != -1) {
                    flowConfigLine["StartTask"].push(task["-id"]);
                  }
                } else {
                  for (var y = 0; y < task["bpmn2:incoming"].length; y++) {
                    if (
                      startEventLine.indexOf(task["bpmn2:incoming"][y]) != -1
                    ) {
                      flowConfigLine["StartTask"].push(task["-id"]);
                    }
                  }
                }
              }

              if (task["bpmn2:outgoing"] != undefined) {
                flowConfigLine[task["-id"]]["outgoing"] =
                  typeof task["bpmn2:outgoing"] == "string"
                    ? [task["bpmn2:outgoing"]]
                    : task["bpmn2:outgoing"];
              }
            }
          }
          if (process["bpmn2:sequenceFlow"] != undefined) {
            var sequenceFlows = [];
            if (
              process["bpmn2:sequenceFlow"].__proto__.constructor.name ==
              "Object"
            ) {
              sequenceFlows.push(process["bpmn2:sequenceFlow"]);
            } else {
              sequenceFlows = process["bpmn2:sequenceFlow"];
            }

            for (var j = 0; j < sequenceFlows.length; j++) {
              var sequenceFlow = sequenceFlows[j];
              flowConfigLine[sequenceFlow["-id"]] = {
                id: sequenceFlow["-id"],
                type: "sequenceFlow",
                sourceRef: sequenceFlow["-sourceRef"],
                targetRef: sequenceFlow["-targetRef"]
              };
              flowConfigLine["Flow"].push(sequenceFlow["-id"]);
            }
          }

          var ExclusiveGateways = [];
          if (process["bpmn2:exclusiveGateway"] != undefined) {
            ExclusiveGateways.push("bpmn2:exclusiveGateway");
          }
          if (process["bpmn2:parallelGateway"] != undefined) {
            ExclusiveGateways.push("bpmn2:parallelGateway");
          }
          if (process["bpmn2:complexGateway"] != undefined) {
            ExclusiveGateways.push("bpmn2:complexGateway");
          }

          for (var i = 0; i < ExclusiveGateways.length; i++) {
            var type = [];
            if (
              process[ExclusiveGateways[i]].__proto__.constructor.name ==
              "Object"
            ) {
              type.push(process[ExclusiveGateways[i]]);
            } else {
              type = process[ExclusiveGateways[i]];
            }
            for (var j = 0; j < type.length; j++) {
              var ExclusiveGateway = type[j];
              flowConfigLine[ExclusiveGateway["-id"]] = {
                id: ExclusiveGateway["-id"],
                type: "ExclusiveGateways",
                types: ExclusiveGateways[i].replace("bpmn2:", ""),
                incoming:
                  typeof ExclusiveGateway["bpmn2:incoming"] == "string"
                    ? [ExclusiveGateway["bpmn2:incoming"]]
                    : ExclusiveGateway["bpmn2:incoming"],
                outgoing:
                  typeof ExclusiveGateway["bpmn2:outgoing"] == "string"
                    ? [ExclusiveGateway["bpmn2:outgoing"]]
                    : ExclusiveGateway["bpmn2:outgoing"]
              };
              flowConfigLine["Gateway"].push(ExclusiveGateway["-id"]);
            }
          }

          if (process["bpmn2:endEvent"] != undefined) {
            var endEvents = [];
            if (
              process["bpmn2:endEvent"].__proto__.constructor.name == "Object"
            ) {
              endEvents.push(process["bpmn2:endEvent"]);
            } else {
              endEvents = process["bpmn2:endEvent"];
            }
            for (var j = 0; j < endEvents.length; j++) {
              var endEvent = endEvents[j];
              flowConfigLine[endEvent["-id"]] = {
                id: endEvent["-id"],
                type: "endEvent",
                incoming:
                  typeof endEvent["bpmn2:incoming"] == "string"
                    ? [endEvent["bpmn2:incoming"]]
                    : endEvent["bpmn2:incoming"]
              };
              flowConfigLine["EndEvent"].push(endEvent["-id"]);
            }
          }
        }
      }
      //其他信息整理

      return flowConfigLine;
    },
    //流程保存
    save() {
      var that = this;
      this.$confirm(
        "此操作将保存该流程图形、节点、分支等配置信息, 是否继续?",
        "提示",
        {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          type: "warning"
        }
      )
        .then(() => {
          that.bpmnModeler.saveXML({ format: true }, function (err, xml) {
           //console.log(xml)
            that.mainInfo.flowInfoBase = xml;
            that.mainInfo.flowConfigLine = JSON.stringify(
              that.getFlowConfigLine(xml),
              null,
              2
            );
            //return;
            that.bpmnModeler.saveSVG({ format: true }, function (err, svg) {
              that.mainInfo.flowInfoSvg = svg;
              let info = {
                id: that.mainInfo.id,
                flowInfoBase: encodeURI(that.mainInfo.flowInfoBase),
                flowInfoSvg: encodeURI(that.mainInfo.flowInfoSvg),
                flowConfigLine: that.mainInfo.flowConfigLine
              }
              putObj(info)
                .then(res => {
                  if (res.data.code == "0") {
                    Message({
                      message: "配置信息保存成功...",
                      type: "success",
                      duration: 3 * 1000
                    });
                    if (that.undodata.length > 1) {
                      that.undodata.splice(0, that.undodata.length - 1);
                    }
                  } else {
                    Message({
                      message: res.msg,
                      type: "error",
                      duration: 3 * 1000
                    });
                  }
                })
                .catch(error => {
                 //console.log(error);
                });
            });
          });
        })
        .catch(() => {
          this.$message({
            type: "info",
            message: "已取消操作"
          });
        });
    },
    undo() {
      this.selectType = null;
      var that = this;
      this.bpmnModeler.importXML(
        this.undodata[this.undodata.length - 2],
        function (err) {
          that.undodata.splice(that.undodata.length - 1, 1);
        }
      );
    },
    szjd() {
      //设置节点
      this.$refs.task.init(this.mainInfo.id, this.selectId, this.selectData);
    },
    szfz() {
      //设置分支
      this.$refs.gateway.init(this.mainInfo.id, this.selectId, this.selectData);
    },
    cacel() {
      this.$emit("loadData");
    }
  }
};
</script>

<style>
.szbnt {
  position: absolute;
  right: 30px;
  bottom: 40px;
  width: 400px;
  height: 40px;
}
.containers {
  /* position: absolute; */
  background-color: #ffffff;
  width: 100%;
  height: 100%;
}
.canvas {
  width: 100%;
  height: 100%;
}
.panel {
  position: absolute;
  right: 0;
  top: 0;
  width: 300px;
}

.bpmn .el-dialog__body {
  height: 80vh;
}
</style>
